package com.muyan.netty.nettysocket;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 单客户端多连接
 */
public class MultiChannelClient {

    private Bootstrap bootstrap = new Bootstrap();

    private List<Channel> channels = new ArrayList<Channel>();

    /**
     * channel引用计数器
     */
    private AtomicInteger index = new AtomicInteger();

    public void init(int count) {
        //工作线程
        EventLoopGroup worker = new NioEventLoopGroup();

        try {
            //设置线程池
            bootstrap.group(worker);

            //设置socket工厂
            bootstrap.channel(NioSocketChannel.class);

            //设置管道
            bootstrap.handler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(Channel ch) {
                    ch.pipeline().addLast(new StringDecoder())
                            .addLast(new StringEncoder())
                            .addLast(new ClientHandler());
                }
            });

            for (int i = 0; i < count; i++) {
                ChannelFuture future = bootstrap.connect("127.0.0.1", 10101);
                channels.add(future.channel());
            }

        } catch (Exception ignore) {

        }

    }

    public Channel nextChannel() {
        return getFirstActiveChannel(0);
    }

    private Channel getFirstActiveChannel(int i) {
        Channel channel = channels.get(Math.abs(this.index.getAndIncrement() % channels.size()));
        if (!channel.isActive()) {
            //重连
            reconnect(channel);

            //如果断开连接了，获取下一个channel
            if (i >= channels.size()) {
                throw new RuntimeException("没有可用的连接了");
            }
            return getFirstActiveChannel(i + 1);
        }
        return channel;
    }

    private void reconnect(Channel channel) {
        synchronized (channel) {//此处需要优化
            if (channels.indexOf(channel) == -1) {
                return;
            }
            Channel newChannel = bootstrap.connect("127.0.0.1", 10101).channel();
            channels.set(channels.indexOf(channel), newChannel);

        }
    }

}